package com.business_clean.app.uitl.share

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import java.io.*

/**
 * 微信分享单独的图片处理
 */
object SocialBitmapUtils {


    // -------------------------- 图片相关-------------------------------
    // -------------------------- 图片相关-------------------------------
    // -------------------------- 图片相关-------------------------------


    class Size(var width: Int, var height: Int)

    /**
     * 根据kb计算缩放后的大约宽高
     *
     * @param originSize 图片原始宽高
     * @param maxSize    byte length
     * @return 大小
     */
    private fun calculateSize(originSize: Size, maxSize: Int): Size {
        val bw = originSize.width
        val bh = originSize.height
        // 如果本身已经小于，就直接返回
        if (bw * bh <= maxSize) {
            return Size(bw, bh)
        }
        // 拿到大于1的宽高比
        var isHeightLong = true
        var bitRatio = bh * 1f / bw
        if (bitRatio < 1) {
            bitRatio = bw * 1f / bh
            isHeightLong = false
        }
        // 较长边 = 较短边 * 比例(>1)
        // maxSize = 较短边 * 较长边 = 较短边 * 较短边 * 比例(>1)
        // 由此计算短边应该为 较短边 = sqrt(maxSize/比例(>1))
        val thumbShort = Math.sqrt((maxSize / bitRatio).toDouble()).toInt()
        // 较长边 = 较短边 * 比例(>1)
        val thumbLong = (thumbShort * bitRatio).toInt()
        return if (isHeightLong) {
            Size(thumbShort, thumbLong)
        } else {
            Size(thumbLong, thumbShort)
        }
    }

    /**
     * 获取图片大小
     *
     * @param filePath 路径
     * @return Size
     */
    private fun getBitmapSize(filePath: String): Size {
        // 仅获取宽高
        val options = BitmapFactory.Options()
        // 该属性设置为 true 只会加载图片的边框进来，并不会加载图片具体的像素点
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(filePath, options)
        // 获得原图的宽和高
        val outWidth = options.outWidth
        val outHeight = options.outHeight
        return Size(outWidth, outHeight)
    }

    /**
     * 使用 path decode 出来一个差不多大小的，此时因为图片质量的关系，可能大于kbNum
     *
     * @param filePath path
     * @param maxSize  byte
     * @return bitmap
     */
    private fun getMaxSizeBitmap(filePath: String, maxSize: Int): Bitmap {
        val originSize = getBitmapSize(filePath)
//        LoggerUtil.e("原始图片大小 = " + originSize.width + " * " + originSize.height)
        var sampleSize = 0
        // 我们对较小的图片不进行采样，因为采样只是尽量接近 32k 和避免占用大量内存
        // 对较小图片进行采样会导致图片更模糊，所以对不大的图片，直接走后面的细节调整
        if (originSize.height * originSize.width < 400 * 400) {
            sampleSize = 1
        } else {
            val size = calculateSize(originSize, maxSize * 5)
//            LoggerUtil.e("目标图片大小 = " + size.width + " * " + size.height)
            while (sampleSize == 0
                || originSize.height / sampleSize > size.height
                || originSize.width / sampleSize > size.width) {
                sampleSize += 2
            }
        }
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = false
        options.inSampleSize = sampleSize
        options.inMutable = true
        val bitmap = BitmapFactory.decodeFile(filePath, options)
//        LoggerUtil.e("sample size = " + sampleSize + " 采样后 bitmap大小 = " + bitmap.byteCount)
        return bitmap
    }


    /**
     * 创建指定大小的bitmap的byte流，大小 <= maxSize
     *
     * @param srcBitmap bitmap
     * @param maxSize   kb,example 32kb
     * @return byte流
     */
    private fun getStaticSizeBitmapByteByBitmap(bitmapByte: ByteArray, maxSize: Int, format: Bitmap.CompressFormat): ByteArray? {
        var bitmap = BitmapFactory.decodeByteArray(bitmapByte, 0, bitmapByte.size);
        // 首先进行一次大范围的压缩
        var tempBitmap: Bitmap
        val output = ByteArrayOutputStream()
        // 设置矩阵数据
        val matrix = Matrix()

        bitmap.compress(format, 100, output)
        // 如果进行了上面的压缩后，依旧大于32K，就进行小范围的微调压缩
        var bytes = output.toByteArray()
//        LoggerUtil.e("开始循环压缩之前 bytes = " + bytes.size)
        while (bytes.size > maxSize) {
            matrix.setScale(0.9f, 0.9f)//每次缩小 1/10
            tempBitmap = bitmap
            bitmap = Bitmap.createBitmap(
                tempBitmap, 0, 0,
                tempBitmap.width, tempBitmap.height, matrix, true)
            recyclerBitmaps(tempBitmap)
            output.reset()
            bitmap.compress(format, 100, output)
            bytes = output.toByteArray()
//            LoggerUtil.e("压缩一次 bytes = " + bytes.size)
        }
//        LoggerUtil.e("压缩后的图片输出大小 bytes = " + (bytes.size / 1024))
        recyclerBitmaps(bitmap)
        return bytes
    }

    /**
     * 根据路径获取指定大小的图片
     * @param bitmap
     * @return byte[]
     */
    fun getStaticSizeBitmapByteByPath(bitmap: Bitmap, size: Int): ByteArray? {
        val byteArrayOutputStream = ByteArrayOutputStream()
        if (bitmap != null) { //防止bitmap会回收传图像数据（字节流）出去
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
            return getStaticSizeBitmapByteByBitmap(byteArrayOutputStream.toByteArray(), size, Bitmap.CompressFormat.JPEG)
        }
        return null
    }


    private fun recyclerBitmaps(vararg bitmaps: Bitmap?) {
        try {
            for (bitmap in bitmaps) {
                if (bitmap != null && !bitmap.isRecycled) {
                    bitmap.recycle()
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }


    /**
     * 压缩图片到指定大小
     * @param bitmap 原始图片
     * @param maxSize 目标大小（字节数）
     * @return 压缩后的图片字节数组
     */
    fun compressToSize(bitmap: Bitmap, maxSize: Int): ByteArray {
        val outputStream = ByteArrayOutputStream()
        var quality = 100
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)

        while (outputStream.toByteArray().size > maxSize && quality > 0) {
            outputStream.reset()
            quality -= 10
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream)
        }
//        LoggerUtil.e("压缩后的图片输出大小 bytes = " + (outputStream.toByteArray().size / 1024))

        return outputStream.toByteArray()
    }

}
